package sh.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.util.Date;

public class JwtUtil {
    /**
     * 加密密钥
     */
public static final String SECRET = "lqwedhuiob87562387456";
    /**
     * 发行人
     */
    public static final String ISSUER = "ld";
    /**
     * 存放到 jwt 中 用户 ID 的 key
     */
    public static final String USERID = "userId";
    /**
     * 存放到 jwt 中 用户自定义数据的 key( 比如可以存放 整个用户对象/权限数据)
     */
    public static final String DATA = "data";
    /**
     * 过期时间三小时(根据实际项目来确定)
     */
    public static final Long EXPIRE_TIME = 180*1000L;
    /**
     * 签名的方法 : 生成 jwt token
     * @param data : 用于存放用户自定义的数据
     * @param userId : 登陆成功后的用户 id
     * @param <T> : 类型 * @return
     */
    public static<T> String sign(T data , Integer userId){
        try {
            // 指定加密算法
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            // 指定过期时间
            Date expire = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            // 利用 jackson 将 data 转换成json 数据
            ObjectMapper objectMapper =
                    new ObjectMapper();
            String jsonData = objectMapper.writeValueAsString(data);
            // 生成 token
            return JWT.create()
            // 存放用户 id 到有效载荷
                    .withClaim(USERID, userId)
            // 存放自定义数据到有效载荷
                    .withClaim(DATA,
                            jsonData)
            // 指定过期时间
                    .withExpiresAt(expire)// 指定发行人
                    .withIssuer(ISSUER)
                    .sign(algorithm);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            // 这个地方也可以全局异常处理
            return null;
        }
    }
    /**
     *验证 token 的正确性
     *@param token
     *@param userId
     *@return
     */
    public static Boolean verfy(String token, Integer userId){
        try {
            // 加密算法
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            // 获取验证器
            JWTVerifier verifier = JWT.require(algorithm)
            // 指定 userId
                    .withClaim(USERID, userId)
            // 指定发行人
                    .withIssuer(ISSUER)
                    .build();
            // 验证
            verifier.verify(token);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     *获取 jwt 中存放的用户 ID
     *@param token
     *@return
     */
    public static Integer getUserId(String token){
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(USERID).asInt();
        } catch (JWTDecodeException e) {e.printStackTrace();
            return null;
        }
    }
    /**
     *获取保存的自定义数据
     *@param token
     *@param tClass
     *@param <T>
     *@return
     */
    public static<T> T getData(String token,Class<T> tClass){
        try {
            DecodedJWT jwt = JWT.decode(token);
            // 获取保存的 data
            String data = jwt.getClaim(DATA).asString();
            // 利用 Jackson 进行 json 字符串转对象
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.readValue(data, tClass);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}
